package com.cloudsea.yunhaianalysis.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cloudsea.yunhaianalysis.entity.Events;
import com.cloudsea.yunhaianalysis.entity.SalesAnalysis;
import com.cloudsea.yunhaianalysis.mapper.EventsMapper;
import com.cloudsea.yunhaianalysis.mapper.SalesAnalysisMapper;
import com.cloudsea.yunhaianalysis.service.ExternalApiService;
import com.cloudsea.yunhaianalysis.service.ForecastService;
import com.cloudsea.yunhaianalysis.vo.ForecastVO;
import com.cloudsea.yunhaistores.entity.Skus;
import com.cloudsea.yunhaistores.entity.Spus;
import com.cloudsea.yunhaistores.mapper.SkusMapper;
import com.cloudsea.yunhaistores.mapper.SpusMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
public class ForecastServiceImpl implements ForecastService {

    @Autowired private ExternalApiService externalApiService;
    @Autowired private SalesAnalysisMapper salesAnalysisMapper;
    @Autowired private SkusMapper skusMapper;
    @Autowired private SpusMapper spusMapper;
    @Autowired private EventsMapper eventsMapper;

    @Override
    public ForecastVO generateForecast(Long storeId, LocalDate targetDate) {
        ForecastVO forecast = new ForecastVO();
        forecast.setForecastDate(targetDate);

        // 步骤1: 获取【未来】目标日期的外部环境特征
        // 【核心修正】调用获取【天气预报】的方法
        Map<String, String> weatherInfo = externalApiService.getWeatherForecast(targetDate);
        Map<String, Object> holidayInfo = externalApiService.getHolidayInfo(targetDate);

        ForecastVO.EnvironmentInfo env = new ForecastVO.EnvironmentInfo();
        env.setWeather(weatherInfo.get("weatherDay"));
        env.setTemperature(String.format("%s°C ~ %s°C", weatherInfo.get("minTemp"), weatherInfo.get("maxTemp")));
        env.setHolidayInfo((String) holidayInfo.get("holidayName"));
        forecast.setEnvironment(env);
        //  查询商家自定义事件
        QueryWrapper<Events> eventWrapper = new QueryWrapper<>();
        eventWrapper.eq("store_id", storeId).eq("event_date", targetDate);
        List<Events> customEvents = eventsMapper.selectList(eventWrapper);

        // 步骤2: 查找历史上的“相似日”作为预测基准
        // (简化策略：直接使用上周同日)
        LocalDate similarDate = targetDate.minusWeeks(1);

        // 步骤3: 查询“相似日”当天的销售数据
        QueryWrapper<SalesAnalysis> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("store_id", storeId).eq("record_date", similarDate);
        List<SalesAnalysis> baselineSales = salesAnalysisMapper.selectList(queryWrapper);

        if (baselineSales.isEmpty()) {
            forecast.setItemForecasts(Collections.emptyList());
            return forecast; // 如果没有历史数据，无法预测
        }

        // 为了获取商品名，需要批量查询SKU和SPU信息
        List<Long> skuIds = baselineSales.stream().map(SalesAnalysis::getSkuId).collect(Collectors.toList());
        Map<Long, Skus> skuMap = skusMapper.selectBatchIds(skuIds).stream().collect(Collectors.toMap(Skus::getId, sku -> sku));
        List<Long> spuIds = skuMap.values().stream().map(Skus::getSpuId).distinct().collect(Collectors.toList());
        Map<Long, Spus> spuMap = spusMapper.selectBatchIds(spuIds).stream().collect(Collectors.toMap(Spus::getId, spu -> spu));

        // 步骤4: 基于基准数据，进行规则修正并组装最终结果
        List<ForecastVO.ItemForecast> itemForecasts = baselineSales.stream().map(sale -> {
            ForecastVO.ItemForecast item = new ForecastVO.ItemForecast();
            Skus sku = skuMap.get(sale.getSkuId());
            if (sku != null) {
                Spus spu = spuMap.get(sku.getSpuId());
                item.setSkuId(sku.getId());
                item.setSkuName(sku.getSkuName());
                item.setSpuName(spu.getSpuName());
            }

            int baseline = sale.getQuantitySold();
            item.setBaselineSales(baseline);

            // --- 简单的规则修正引擎 ---
            double adjustedQuantity = baseline;
            String reason = "基于上周同日销量";

            // 获取目标日和基准日的天气信息用于对比
            int targetTemp = Integer.parseInt(weatherInfo.get("maxTemp"));
            // 为了获取基准日天气，我们需要从数据库中查询，这里先简化处理
            Optional<SalesAnalysis> baselineAnalysis = baselineSales.stream().filter(s -> s.getSkuId().equals(sale.getSkuId())).findFirst();
            int baselineTemp = baselineAnalysis.map(SalesAnalysis::getMaxTemperature).orElse(22);

            if (targetTemp > baselineTemp + 5) {
                adjustedQuantity *= 1.15; // 销量上浮15%
                reason += "，因天气明显炎热上调15%";
            }

            for (Events event : customEvents) {
                if ("PROMOTION".equals(event.getEventType())) {
                    // 如果有促销活动，简单地将所有商品预测销量上浮20%
                    adjustedQuantity *= 1.20;
                    reason += "，因" + event.getDescription() + "上调20%";
                }
                // ... 可以为不同 eventType 添加更复杂的规则 ...
            }

            item.setSuggestedQuantity((int) Math.round(adjustedQuantity));
            item.setReason(reason);

            return item;
        }).collect(Collectors.toList());

        forecast.setItemForecasts(itemForecasts);
        return forecast;
    }
}
